/*
  LinPVR - Linux Personal Video Recorder
  Copyright (C) 2006 Kamil Pawlowski <kamilpe@gmail.com>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <glade/glade.h>
#include "gui.h"
#include "ogg_dec.h"
#include "debug.h"
#include "main.h"
#include "config.h"

/* --- private functions --- */

int  linpvr_stop_mode(linpvr_t *linpvr);
int  linpvr_start_mode(linpvr_t *linpvr, int mode);
void linpvr_gui_to_mode(linpvr_t *linpvr, int mode);

/* --- bodies of functions ---*/

int linpvr_stop_mode(linpvr_t *linpvr)
{
  switch (linpvr->mode) {

  case MODE_NO_DEVICE:
    {
      if (linpvr->mode != MODE_NO_DEVICE) {
	DEBUG_RETVAL(ERR_NO_DEVICE);
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }
      break;
    }
  case MODE_TV:
    {
      g_source_remove(linpvr->preview.previd);
      if (DEBUG_RETVAL(capture_stop(&linpvr->capture)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }     
      capture_destroy(&linpvr->capture);
      break;
    }
  case MODE_RECORD:
    {
      g_source_remove(linpvr->preview.previd);
      if (DEBUG_RETVAL(capture_stop(&linpvr->capture)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }     
      ogg_enc_close(&linpvr->ogg_enc);
      capture_destroy(&linpvr->capture);
      if (DEBUG_RETVAL(library_refresh_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "media_library")),
					    linpvr->config.library,1)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }
      break;
    }
  }
  return 0;
}

int linpvr_start_mode(linpvr_t *linpvr, int mode)
{
  linpvr->mode = mode;
  switch (linpvr->mode) {
  case MODE_TV:
    {
      if (DEBUG_RETVAL(capture_create(&linpvr->capture, 384, 288)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }
      videodev_attach(&linpvr->video, &linpvr->capture);
      if (DEBUG_RETVAL(capture_start(&linpvr->capture)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }
      linpvr->preview.previd = g_timeout_add(40, (GtkFunction)preview_update, &linpvr->preview);
      break;
    }
  case MODE_RECORD:
    {
      char *path;

      if (DEBUG_RETVAL(capture_create(&linpvr->capture, 384, 288)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }

      videodev_attach(&linpvr->video, &linpvr->capture);

      path = (char*)library_gen_name(linpvr->config.library);
      set_properties_by_gui(linpvr->glade, &linpvr->capture);
      ogg_enc_init(&linpvr->ogg_enc, &linpvr->capture);
      
      if (DEBUG_RETVAL(ogg_enc_open(&linpvr->ogg_enc, path)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }

      if (DEBUG_RETVAL(capture_start(&linpvr->capture)) < 0) {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	return -1;
      }

      linpvr->preview.previd = g_timeout_add(1000, (GtkFunction)preview_update, &linpvr->preview);
      break;
    }
  }

  return 0;
}

void linpvr_gui_to_mode(linpvr_t *linpvr, int mode)
{
  GtkStatusbar *statusbar;

  statusbar = GTK_STATUSBAR(glade_xml_get_widget(linpvr->glade, "statusbar"));
  if (GTK_IS_STATUSBAR(statusbar)) {

    /* first i get all widgets what i need */
    gint context_id = gtk_statusbar_get_context_id(statusbar, "Application status");
    GtkWidget *record = glade_xml_get_widget(linpvr->glade, "record");
    GtkWidget *video = glade_xml_get_widget(linpvr->glade, "video");
    GtkWidget *stop = glade_xml_get_widget(linpvr->glade, "stop");
    GtkWidget *quality = glade_xml_get_widget(linpvr->glade, "quality_select");
    GtkWidget *channels = glade_xml_get_widget(linpvr->glade, "channels_list");
    GtkWidget *position = glade_xml_get_widget(linpvr->glade, "playback_position");
    gtk_statusbar_pop(statusbar, context_id);

    switch (mode) {
    case MODE_NO_DEVICE:
      gtk_widget_set_sensitive(record, FALSE);
      gtk_widget_set_sensitive(video, TRUE);
      gtk_widget_set_sensitive(stop, FALSE);
      gtk_widget_set_sensitive(quality, TRUE);
      gtk_widget_set_sensitive(channels, FALSE);
      gtk_widget_set_sensitive(position, FALSE);
      gtk_statusbar_push (statusbar, context_id, "No device open. Try Ctrl+W to select another device");
      break;
    case MODE_IDLE:
      gtk_widget_set_sensitive(record, FALSE);
      gtk_widget_set_sensitive(video, TRUE);
      gtk_widget_set_sensitive(stop, FALSE);
      gtk_widget_set_sensitive(quality, TRUE);
      gtk_widget_set_sensitive(channels, TRUE);
      gtk_widget_set_sensitive(position, FALSE);
      gtk_statusbar_push (statusbar, context_id, "Idle");
      break;
    case MODE_TV:
      gtk_widget_set_sensitive(record, TRUE);
      gtk_widget_set_sensitive(video, TRUE);
      gtk_widget_set_sensitive(stop, FALSE);
      gtk_widget_set_sensitive(quality, TRUE);
      gtk_widget_set_sensitive(channels, TRUE);
      gtk_widget_set_sensitive(position, FALSE);
      gtk_statusbar_push (statusbar, context_id, "Watching TV preview");
      break;
    case MODE_RECORD:
      gtk_widget_set_sensitive(record, FALSE);
      gtk_widget_set_sensitive(video, FALSE);
      gtk_widget_set_sensitive(stop, TRUE);
      gtk_widget_set_sensitive(quality, FALSE);
      gtk_widget_set_sensitive(channels, FALSE);
      gtk_widget_set_sensitive(position, FALSE);
      gtk_statusbar_push (statusbar, context_id, "Recording from TV");
      break;
    case MODE_PLAY:
      gtk_widget_set_sensitive(record, TRUE);
      gtk_widget_set_sensitive(video, TRUE);
      gtk_widget_set_sensitive(stop, TRUE);
      gtk_widget_set_sensitive(quality, TRUE);
      gtk_widget_set_sensitive(channels, TRUE);
      gtk_widget_set_sensitive(position, TRUE);
      gtk_statusbar_push (statusbar, context_id, "Playback from video library");
      break;
    }
  }
}

void linpvr_switch_mode(linpvr_t *linpvr, int mode) {

  DEBUG_ENTER("linpvr_switch_mode");

  if (linpvr_stop_mode(linpvr) < 0)
    return;
  if (linpvr_start_mode(linpvr,mode) < 0)
    return;
  linpvr_gui_to_mode(linpvr,mode);
}
void linpvr_init(linpvr_t *linpvr) {
  DEBUG_ENTER("linpvr_init");
  
  linpvr->mode = MODE_NO_DEVICE;
  linpvr->preview.capture = &linpvr->capture;

  /* open video device */
  if (DEBUG_RETVAL2(videodev_open(&linpvr->video, linpvr->config.video_device),
		    linpvr->config.video_device) < 0) {
    show_error_report(linpvr->glade, debug_message());
    linpvr_switch_mode(linpvr, MODE_NO_DEVICE);
  } else {
    /* video device opened so go to idle status */
    linpvr_switch_mode(linpvr, MODE_IDLE);
  }
}

void linpvr_uninit(linpvr_t *linpvr) {
  DEBUG_ENTER("linpvr_uninit");
  linpvr_switch_mode(linpvr, MODE_NO_DEVICE);
  videodev_close(&linpvr->video);
}


/*
  Main routines
 */

/* this thread make initialisation of all program data and switch from splash to main */
gpointer *init_program(linpvr_t *linpvr)
{
  int ret;
  GtkWindow *mainwin, *splash;
  DEBUG_ENTER("init_program");

  gdk_threads_enter();

  /* read configuration */
  config_default(&linpvr->config);
  if (DEBUG_RETVAL(config_read(&linpvr->config)) < 0)
    show_error_report(linpvr->glade, debug_message());

  /* Initialize linpvr object */
  linpvr_init(linpvr);
  if (linpvr->mode == MODE_IDLE)
    linpvr_switch_mode(linpvr, MODE_TV);

  /* Prepare all GTK objects */
  preview_init(&linpvr->preview, linpvr->glade);
  prepare_library_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "media_library")));
  prepare_formats_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "formats_list")));
  prepare_devices_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "devices_list")));
  prepare_channels_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "channels_list")));
  prepare_sheduler_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "sheduler_jobs")));
  if (DEBUG_RETVAL(library_refresh_tree(GTK_TREE_VIEW(glade_xml_get_widget(linpvr->glade, "media_library")),
					linpvr->config.library, 0)) < 0)
    {
	show_error_report(linpvr->glade, debug_message());
	linpvr_main_quit();
	gdk_threads_leave();
	g_thread_exit(NULL);
    }

  /* Switch from Splash to Main window */
  //sleep(1);
  mainwin = GTK_WINDOW(glade_xml_get_widget(linpvr->glade, "mainwin"));
  splash = GTK_WINDOW(glade_xml_get_widget(linpvr->glade, "splash"));
  gtk_widget_show(GTK_WIDGET(mainwin));
  gtk_widget_set_sensitive(GTK_WIDGET(mainwin), TRUE);
  gtk_widget_hide(GTK_WIDGET(splash));
  gdk_threads_leave();

  g_thread_exit(NULL);
}

/* FIXME: make this structure defined as local and pass to glade signals */
linpvr_t linpvr;
int main(int argc, char **argv)
{
  /*
  gtk_init(&argc, &argv);
  g_thread_init(NULL);
  gdk_threads_init();

  glade_init();
  linpvr.glade = glade_xml_new(PACKAGE_DATA_DIR "/" PACKAGE "/gtk_windows.glade",NULL,NULL);
  glade_xml_signal_autoconnect(linpvr.glade);

  g_thread_create((GThreadFunc)init_program, &linpvr, FALSE, NULL);
  gtk_main();

  debug_flush();
  */

  audiodev_t audio;
  if (DEBUG_RETVAL(audiodev_open(&audio, "plughw:0,0", 44100, 2, AUDIO_CAPTURE))<0) {
    debug_flush();
    return 0;
  }

  audiodev_close(&audio);

  return 0;
}

void linpvr_main_quit() {
  if (linpvr.mode != MODE_NO_DEVICE)
    linpvr_uninit(&linpvr);
  gtk_main_quit();
}
